home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / plus.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  13KB  |  619 lines

  1. /* OS- and machine-dependent stuff for HP 110+ running MS-DOS */
  2. #if defined(__TURBOC__)
  3. #pragma inline
  4. #include <stdio.h>
  5. #include "config.h"
  6. #if defined(PLUS)
  7. #include "global.h"
  8. #include "8250.h"
  9. #include "asy.h"
  10. #include "plus.h"
  11. #include "iface.h"
  12.  
  13. struct asy asy[ASY_MAX];
  14. unsigned nasy;
  15. byte model;
  16.  
  17. void    _Cdecl    __int__        (int interruptnum);
  18. void    interrupt     (* _Cdecl getvect(int interruptno)) ();
  19. #define geninterrupt(i) __int__(i)
  20.  
  21. extern unsigned char intstk[];
  22. extern unsigned int sssave, spsave;
  23. /*
  24.  =================================================================
  25.  */
  26. int16 modemdev, serialdev;
  27. struct plusasy plusasy[ASY_MAX];
  28. /* ASY interrupt handlers */
  29. byte modemconfig, serialconfig;
  30. extern void interrupt plustxsvec();
  31. extern void interrupt plusrxsvec();
  32. extern void interrupt plustxmvec();
  33. extern void interrupt plusrxmvec();
  34. byte *com1_name="COM1";         /* file to open  for serial            */
  35. byte *com3_name="COM3";         /* file to open for modem            */
  36. int com1handle;            /* file handle saved here            */
  37. int com3handle;            /* file handle saved here            */
  38. byte *ioctlon1="M1;";           /* IOCTL to turn on  serial port            */
  39. byte *ioctloff1="M3;";          /* IOCTL to turn off serial port            */
  40. byte *ioctlon3="M4;";           /* IOCTL to turn on  modem port            */
  41. byte *ioctloff3="M5;";          /* IOCTL to turn off modem port            */
  42.  
  43. /* Initialize asynch port "dev" */
  44. int
  45. asy_init(dev,arg1,arg2,bufsize)
  46. int16 dev;
  47. char *arg1,*arg2;
  48. unsigned bufsize;
  49. {
  50.     register unsigned base;
  51.     register struct fifo *fp;
  52.     register struct asy *ap;
  53.   
  54.     ap = &asy[dev];
  55.     ap->addr = htoi(arg1);
  56.     ap->vec = htoi(arg2);
  57.     /* Set up receiver FIFO */
  58.     fp = &ap->fifo;
  59.     if((fp->buf = malloc(bufsize)) == NULLCHAR){
  60.         printf("asy%d: No space for rx buffer\r\n");
  61.         fflush(stdout);
  62.         return;
  63.     }
  64.     fp->bufsize = bufsize;
  65.     fp->wp = fp->rp = fp->buf;
  66.     fp->cnt = 0;
  67.   
  68.     base = ap->addr;
  69.     /* Purge the receive data buffer
  70.      * Set line control register: 8 bits, no parity
  71.      *
  72.      * Turn on receive interrupt enable, leave transmit
  73.      * interrupts turned off for now
  74.      *
  75.      * Set modem control register: assert DTR, RTS, turn on serial
  76.      * port
  77.      *
  78.      * Enable rx interrupt
  79.      */
  80.     (void)init_com(dev,'N',1);
  81.     /*
  82.      * set calibration in delay
  83.      */
  84.      /*
  85.       * turn off lousy beeper on ring interrupts.
  86.       */
  87.      _AL=2;
  88.      __int__(0x59);
  89.     /* Set interrupt vector to SIO handler
  90.      *  DON'T bump them by 8 as we use the actual
  91.      *  interrupt numbers, not the number -8 as in
  92.      *  the pc asy entry.
  93.      *
  94.      *  If the computer is a portable only the serial interrupts are used
  95.      *  If the computer is a P+ both serial and modem interrupts are used
  96.      *
  97.      *                     110    110p serial   110p modem
  98.      *          rx vector  0x4f       0x4f       0x4e
  99.      *          tx vector  0x4a       0x4a       0x40
  100.      *          base addr  0xa4       0x44         0xa4   
  101.      *
  102.      */
  103.     if(base==0x44 || model==1) {
  104.     plusasy[dev].oldrx=getvect(0x4f);
  105.     plusasy[dev].oldtx=getvect(0x4a);
  106.     if(model==1) {
  107.         asy[dev].addr=0xa4;
  108.             setvect(0x4a,plustxmvec);
  109.             setvect(0x4f,plusrxmvec);
  110.         modemdev=dev;
  111.     }
  112.     else {
  113.         setvect(0x4a,plustxsvec);
  114.         setvect(0x4f,plusrxsvec);
  115.         serialdev=dev;
  116.     }
  117.     }
  118.     else { /* address not 0x44 and not a portable, must be plus modem */
  119.     plusasy[dev].oldrx=getvect(0x4e);
  120.     plusasy[dev].oldtx=getvect(0x40);
  121.     setvect(0x40,plustxmvec);
  122.     setvect(0x4e,plusrxmvec);
  123.     modemdev=dev;
  124.     }
  125. } /* asy_init */
  126.  
  127. int
  128. asy_stop(iface)
  129. struct interface *iface;
  130. {
  131.     register unsigned base;
  132.     register struct asy *ap;
  133.   
  134.     ap = &asy[iface->dev];
  135.     base = ap->addr;
  136.   
  137. /*
  138.  * hardware ints off
  139.  */
  140.     outportb(base+INTRCONTROL,(unsigned char)0xf0);
  141. /*
  142.  * turn off power to the serial port and
  143.  * Restore original interrupt vectors
  144.  */
  145.     if(base==0x44 || model==1) {
  146.         serial_power(0);
  147.         setvect(0x4f,plusasy[iface->dev].oldrx);
  148.         setvect(0x4a,plusasy[iface->dev].oldtx);
  149.     }
  150.     else {
  151.         modem_power(0);
  152.         setvect(0x4e,plusasy[iface->dev].oldrx);
  153.         setvect(0x40,plusasy[iface->dev].oldtx);
  154.     }
  155.     return(0);
  156. }
  157.  
  158. /* Asynchronous line I/O control */
  159. asy_ioctl(interface,argc,argv)
  160. struct interface *interface;
  161. int argc;
  162. char *argv[];
  163. {
  164.     if(argc < 1){
  165.         printf("%d\r\n",asy[interface->dev].speed);
  166.         return 0;
  167.     }
  168.     return asy_speed(interface->dev,atoi(argv[0]));
  169. }
  170.  
  171. /* Set asynch line speed */
  172. int
  173. asy_speed(dev,speed)
  174. int16 dev;
  175. int speed;
  176. {
  177.     register unsigned base;
  178.     register int divisor;
  179.     char i_state;
  180.   
  181.     if(speed == 0 || dev >= nasy)
  182.         return;
  183.   
  184.     base = asy[dev].addr;
  185.     asy[dev].speed = speed;
  186. /*
  187.  *  Setup baud rate
  188.  */
  189.     divisor=1333500L/speed - 1;
  190.     i_state = disable();
  191.     outportb((unsigned)(base+BAUDLO), (unsigned char)(divisor));
  192.     outportb((unsigned)(base+BAUDHI), (unsigned char)(divisor>>8));
  193.     restore(i_state);
  194. }
  195.  
  196. /* Send a buffer to serial transmitter */
  197. asy_output(dev,buf,cnt)
  198. unsigned dev;
  199. char *buf;
  200. unsigned short cnt;
  201. {
  202.     register struct dma *dp;
  203.     unsigned base;
  204.     char i_state;
  205.  
  206.     if(cnt == 0)
  207.     return;
  208.     if(dev >= nasy)
  209.         return;
  210.     base = asy[dev].addr;
  211.     dp = &asy[dev].dma;
  212.     i_state = disable();
  213.     if(dp->flags){
  214.         restore(i_state);
  215.         return; /* Already busy */
  216.     }
  217.     dp->data = buf;
  218.     dp->cnt = cnt;
  219.     dp->flags = 1;
  220.     /* Enable transmitter buffer empty interrupt and simulate
  221.      * an interrupt; this will get things rolling.
  222.      */
  223.     clrbit(base+INTRCONTROL,0x80);
  224.     setbit(base+INTRCONTROL,0x40);
  225.     asytxint(dev);
  226.     restore(i_state);
  227. }
  228.  
  229. /* Receive characters from asynch line
  230.  * Returns count of characters read
  231.  */
  232. int16
  233. asy_recv(dev,buf,cnt)
  234. int16 dev;
  235. char *buf;
  236. unsigned cnt;
  237. {
  238.     unsigned tot,n;
  239.     int kbread();
  240.     char i_state;
  241.     struct fifo *fp;
  242.   
  243.     fp = &asy[dev].fifo;
  244.     tot = 0;
  245.     /* Read from serial I/O input buffer */
  246.     i_state = disable();
  247.     for(;;){
  248.         n = min(cnt,fp->cnt);
  249.         if(n == 0)
  250.             break;
  251.         n = min(n,&fp->buf[fp->bufsize] - fp->rp);
  252.         memcpy(buf,fp->rp,n);
  253.         fp->rp += n;
  254.         if(fp->rp >= &fp->buf[fp->bufsize])
  255.             fp->rp = fp->buf;
  256.         fp->cnt -= n;
  257.         buf += n;
  258.         tot += n;
  259.         cnt -= n;
  260.     }
  261.     restore(i_state);
  262.     return tot;
  263.   
  264. }
  265.  
  266. /* Process 110P receiver interrupts */
  267. static
  268. asyrxint(dev)
  269. unsigned dev;
  270. {
  271.     unsigned base;
  272.     register struct fifo *fp;
  273.     char c;
  274.   
  275.     base = asy[dev].addr;
  276.     fp = &asy[dev].fifo;
  277.     c = inportb(base+RXDATA);
  278.     /* Process incoming data;
  279.      * If buffer is full, we have no choice but
  280.      * to drop the character
  281.      */
  282.     if(fp->cnt != fp->bufsize){
  283.         *fp->wp++ = c;
  284.         if(fp->wp == &fp->buf[fp->bufsize])
  285.             /* Wrap around */
  286.             fp->wp = fp->buf;
  287.         fp->cnt++;
  288.     }
  289. }
  290.  
  291. /* Handle 110P transmitter interrupts */
  292. static
  293. asytxint(dev)
  294. unsigned dev;
  295. {
  296.     register struct dma *dp;
  297.     register unsigned base;
  298.   
  299.     base = asy[dev].addr;
  300.     dp = &asy[dev].dma;
  301.     if(!dp->flags){
  302.         /* "Shouldn't happen", but disable transmit
  303.          * interrupts anyway
  304.          */
  305.     setbit(base+INTRCONTROL,0xc0);
  306.     return; /* Nothing to send */
  307.     }
  308.     while(inportb(base+STATUS) & 0x02){
  309.         outportb(base+TXDATA,*dp->data++);
  310.         if(--dp->cnt == 0){
  311.             dp->flags = 0;
  312.             /* Disable transmit interrupts */
  313.             setbit(base+INTRCONTROL,0xc0);
  314.             break;
  315.     }
  316. /*
  317.  * turn em back on, we got more to do
  318.  */
  319.         clrbit(base+INTRCONTROL,0x80);
  320.         setbit(base+INTRCONTROL,0x40);
  321.     }
  322. }
  323.  
  324. int
  325. stxrdy(dev)
  326. int16 dev;
  327. {
  328.     return(!asy[dev].dma.flags);
  329. }
  330. /* Set bit(s) in I/O port */
  331.   
  332. setbit(port,bits)
  333. unsigned port;
  334. char bits;
  335. {
  336.     outportb(port,(char)inportb(port)|bits);
  337. }
  338.  
  339. /* Clear bit(s) in I/O port */
  340. clrbit(port,bits)
  341. unsigned port;
  342. char bits;
  343. {
  344.     outportb(port,(char)(inportb(port) & ~bits));
  345. }
  346.  
  347. int init_com(dev,wordlen,parity)
  348. int dev, wordlen;
  349. char parity;
  350. {
  351.     int i, offset, sconfig;
  352.     i=peek(0xffff,0x0e) & 0xff;
  353.     if(i==0xb6) {
  354.         model=1;            /* portable      */
  355.     asy[dev].addr=0xa4;
  356.         offset=i=0x60;
  357.     }
  358.     else
  359.         if((i=='A') || (i=='B')) {
  360.             model=0;            /* portable plus */
  361.             offset=i=0;
  362.         }
  363.         else
  364.             if(i>0xfb) model=2; /* pc type       */
  365.     if(model==2) {
  366.         return(offset=-1);
  367.     }
  368. /*
  369.  * turn on port
  370.  */
  371.     outportb((unsigned)(asy[dev].addr+INTRCONTROL),
  372.         (unsigned char)0xf0); /* make sure no ints from serial */
  373.     if(offset || asy[dev].addr==0x44) {
  374.     serial_power(1);
  375.     }
  376.     else {
  377.     modem_power(1);
  378.     }
  379.   
  380.     i=wordlen-5;
  381.     if ((i<0) || (i>3)) i=3;
  382.     i=i<<6;
  383.   
  384.     sconfig=i | 2;             /* setup our local copy */
  385.     switch(parity) {
  386.         case 'n':
  387.         case 'N':   i=0;
  388.             break;
  389.         case 'e':
  390.         case 'E':   i=2;
  391.             break;
  392.         case 'o':
  393.         case 'O':   i=3;
  394.             break;
  395.         default:
  396.             i=0;
  397.     }
  398.     i=i<<2;
  399.     sconfig|=i;
  400.     if(offset || asy[dev].addr==0xa4) 
  401.     modemconfig=sconfig;
  402.     else
  403.     serialconfig=sconfig;
  404. /*
  405.  * set up serial configuration register
  406.  */
  407.     outportb((unsigned)(asy[dev].addr+FORMATCONTROL),
  408.         (unsigned char)sconfig);
  409. /*
  410.  * interrupt on data avail
  411.  */
  412.     outportb((unsigned)(asy[dev].addr+INTRCONTROL+offset),
  413.         (unsigned char)0xd0);
  414.     return 4;
  415. } /* init_com */
  416.   
  417. #if 0  
  418. /*
  419.  * This code is if def'ed out. I left it in in case someone wanted to
  420.  *  see how to read these lines.  WA7TAS
  421.  */
  422. /*
  423.  * state of cts and dsr lines are inverted on the portable plus
  424.  *  and not inverted on the portable. CTS is bit 6 on the portable,
  425.  *  and bit 7 on the portable plus. DSR is bit 7 on the portable,
  426.  *  and bit 6 on the portable plus.
  427.  */
  428. int cts()
  429. {
  430.     if(model==1) return((int)(inportb(0x2f) & 0x40));
  431.     return(!((int)(inportb(0x2f) & 0x80)));
  432. } /* cts */
  433.   
  434. int dsr()
  435. {
  436.     if(model==1) return((int)(inportb(0x2f) & 0x80));
  437.     return(!((int)(inportb(0x2f) & 0x40)));
  438. }
  439.  /* dsr */
  440. #endif  
  441.  
  442. void interrupt plustxsvec()
  443. {
  444.     asm mov ds:sssave,ss;
  445.     asm mov ds:spsave,sp;
  446.  
  447.     _BX=intstk;
  448.     _SS=_DS;    
  449.     asm mov sp,bx
  450.  
  451.     asytxint(serialdev);
  452.  
  453.     asm mov sp,ds:spsave;
  454.     asm mov ss,ds:sssave;
  455. } /* plustxsvec */
  456.  
  457. /*
  458.  * see turbo c user's guide page p283
  459.  */
  460. void interrupt plusrxsvec()
  461. {
  462.     register int tchar, dd;
  463.  
  464.     asm mov ds:sssave,ss;
  465.     asm mov ds:spsave,sp;
  466.  
  467.     _BX=intstk;
  468.     _SS=_DS;    
  469.     asm mov sp,bx
  470.  
  471.     if((inportb(SERIAL_STATUS) & 0x80) != 0) asyrxint(serialdev);
  472.     outportb(SERIAL_FMTCNTL,serialconfig | 2);
  473.     tchar=inportb(SERIAL_INTRCNTL);
  474.     tchar|=0x10;
  475.     tchar&=(~0x20);
  476.  
  477.     asm mov sp,ds:spsave;
  478.     asm mov ss,ds:sssave;
  479.  
  480.     outportb(SERIAL_INTRCNTL,tchar);
  481. } /* plusrxsvec */
  482.  
  483. void interrupt plustxmvec()
  484. {
  485.     asm mov ds:sssave,ss;
  486.     asm mov ds:spsave,sp;
  487.  
  488.     _BX=intstk;
  489.     _SS=_DS;    
  490.     asm mov sp,bx
  491.  
  492.     asytxint(modemdev);
  493.  
  494.     asm mov sp,ds:spsave;
  495.     asm mov ss,ds:sssave;
  496. } /* plustxmvec */
  497. /*
  498.  * see turbo c user's guide page p283
  499.  */
  500.  
  501. void interrupt plusrxmvec()
  502. {
  503.     register int tchar, dd;
  504.     asm mov ds:sssave,ss;
  505.     asm mov ds:spsave,sp;
  506.  
  507.     _BX=intstk;
  508.     _SS=_DS;    
  509.     asm mov sp,bx
  510.  
  511.     if((inportb(MODEM_STATUS) & 0x80) != 0) asyrxint(modemdev);
  512.     outportb(MODEM_FMTCNTL,modemconfig | 2);
  513.     tchar=inportb(MODEM_INTRCNTL);
  514.     tchar|=0x10;
  515.     tchar&=(~0x20);
  516.  
  517.     asm mov sp,ds:spsave;
  518.     asm mov ss,ds:sssave;
  519.  
  520.     outportb(MODEM_INTRCNTL,tchar);
  521.  
  522. } /* plusrmsvec */
  523.  
  524. void modem_power(on_off)
  525. int on_off;
  526. {
  527. /*
  528.  * open com3 file see 110+ tech ref page 6-18
  529.  */
  530.     _AX=0x3d02;
  531.     _DX=com3_name;
  532.     geninterrupt(0x21);
  533.     com3handle=_AX;
  534. /*
  535.  * get com3 device status info
  536.  */
  537.     _BX=_AX;
  538.     _AX=0x4400;
  539.     geninterrupt(0x21);
  540. /*
  541.  * set raw bit
  542.  */
  543.     _BX=com3handle;
  544.     _DH=0;
  545.     _DL|=0x20;
  546.     _AX=0x4401;
  547.     geninterrupt(0x21);
  548. /*
  549.  * turn on rs232 port or off
  550.  */
  551.     if(on_off!=0) { /* turn it on */
  552.     _BX=com3handle;
  553.     _DX=ioctlon3;
  554.     _CX=3;
  555.     _AX=0x4403;
  556.     }
  557.     else {
  558.     _DX=ioctloff3;
  559.     _CX=3;
  560.     _AX=0x4403;
  561.     geninterrupt(0x21);
  562. /*
  563.  * close the file handle as we're done with it.
  564.  */
  565.     _BX=com3handle;
  566.     _AX=0x3e00;
  567.     }
  568.     geninterrupt(0x21);
  569. } /* modem_power */
  570.  
  571. void serial_power(on_off)
  572. int on_off;
  573. {
  574. /*
  575.  * open com1 file see 110+ tech ref page 6-18
  576.  */
  577.     _AX=0x3d02;
  578.     _DX=com1_name;
  579.     geninterrupt(0x21);
  580.     com1handle=_AX;
  581. /*
  582.  * get com1 device status info
  583.  */
  584.     _BX=_AX;
  585.     _AX=0x4400;
  586.     geninterrupt(0x21);
  587. /*
  588.  * set raw bit
  589.  */
  590.     _BX=com1handle;
  591.     _DH=0;
  592.     _DL|=0x20;
  593.     _AX=0x4401;
  594.     geninterrupt(0x21);
  595. /*
  596.  * turn on rs232 port or off
  597.  */
  598.     if(on_off!=0) { /* turn it on */
  599.     _BX=com1handle;
  600.     _DX=ioctlon1;
  601.     _CX=3;
  602.     _AX=0x4403;
  603.     }
  604.     else {
  605.     _DX=ioctloff1;
  606.     _CX=3;
  607.     _AX=0x4403;
  608.     geninterrupt(0x21);
  609. /*
  610.  * close the file handle as we're done with it.
  611.  */
  612.     _BX=com1handle;
  613.     _AX=0x3e00;
  614.     }
  615.     geninterrupt(0x21);
  616. } /* serial_power */
  617. #endif  /* if defined(PLUS) */
  618. #endif  /* if defined(__TURBOC__) */
  619.